package edu.umn.se.trap;

import java.util.Map;
import java.util.Vector;

import databases.CurrencyDB;
import databases.KeyNotFoundException;
import edu.umn.se.trap.exceptions.CurrencyException;
import edu.umn.se.trap.exceptions.TrapException;

public class FormFactory {
    /**
     * takes in a java map and turns it into a 'Form' object, so each of the other
     * methods only have to deal with the individual Form object 
     * @param formData - the input data to be transfered into 'Form' form
     * @param description - the form's description
     * @return a new form instance
     */
    public static Form createForm(Map<String, String> formData, String description) throws TrapException
    {
        Form newForm = new Form(formData, description);
        
        CurrencyDB currencyDB = new CurrencyDB();
     
        // from the Map, set all intermediate form data fields here, convert all currency to $US
        // this will be a massive and bloated try block...
        // this try block now just catches any error and lists what function it came from
        try
        {
            
            // 1) fill in the travel details
            String uname = formData.get("USER_NAME");

            String[] depSplit = formData.get("DEPARTURE_DATETIME").split(" ");
            int depDate = Integer.parseInt(depSplit[0]);
            int depTime = Integer.parseInt(depSplit[1]);
            String[] arrSplit = formData.get("ARRIVAL_DATETIME").split(" ");
            int arrDate = Integer.parseInt(arrSplit[0]);
            int arrTime = Integer.parseInt(arrSplit[1]);
            
            boolean cseSpons = false;
            if (formData.get("TRAVEL_TYPE_CSE_SPONSORED") != (null) && formData.get("TRAVEL_TYPE_CSE_SPONSORED").equalsIgnoreCase("yes"))
            {
                cseSpons = true;
            }
            
            boolean dtcSpons = false;
            if (formData.get("TRAVEL_TYPE_DTC_SPONSORED") != (null) && formData.get("TRAVEL_TYPE_DTC_SPONSORED").equalsIgnoreCase("yes"))
            {
                dtcSpons = true;
            }
            
            boolean nonspons = false;
            if (formData.get("TRAVEL_TYPE_NONSPONSORED") != (null) && formData.get("TRAVEL_TYPE_NONSPONSORED").equalsIgnoreCase("yes"))
            {
                nonspons = true;
            }
            
            String emergContact = formData.get("EMERGENCY_CONTACT_NAME");
            if(emergContact == null)
                emergContact = "";
            String emergContactTelNum = formData.get("EMERGENCY_CONTACT_PHONE");
            if(emergContactTelNum == null)
                emergContactTelNum = "";
            String jConfTitle = formData.get("JUSTIFICATION_CONFERENCE_TITLE");
            if(jConfTitle == null)
                jConfTitle = "";
            
            boolean jPresented = false;
            if (formData.get("JUSTIFICATION_PRESENTED").equalsIgnoreCase("yes"))
            {
                dtcSpons = true;
            }
            
            String jPresentationTitle = "";
            String jPresentationAbstract = "";
            String jPresentationAcknowledgement = "";
            if (jPresented)
            {
                jPresentationTitle = formData.get("JUSTIFICATION_PRESENTATION_TITLE");
                jPresentationAbstract = formData.get("JUSTIFICATION_PRESENTATION_ABSTRACT");
                jPresentationAcknowledgement = formData.get("JUSTIFICATION_PRESENTATION_ACKNOWLEDGEMENT");
            }
            
            String jNonspons = "";
            if (nonspons)
            {
                jNonspons = formData.get("JUSTIFICATION_NONSPONSORED");
            }
            
            String jSpons = "";
            if (cseSpons || dtcSpons)
            {
                jSpons = formData.get("JUSTIFICATION_SPONSORED");
            }
            
            TravelDetails TD =  new TravelDetails(uname,
                     depDate,
                     depTime,
                     arrDate,
                     arrTime,
                     cseSpons,
                     dtcSpons,
                     nonspons,
                     emergContact,
                     emergContactTelNum,
                     jConfTitle,
                     jPresented,
                     jPresentationTitle,
                     jPresentationAbstract,
                     jPresentationAcknowledgement,
                     jNonspons,
                     jSpons);
            
            newForm.setTravelDetails(TD);
            
            // 2) fill in each day with meals, incidentals, and lodging, then add to days vec
            int numDays = Integer.parseInt(formData.get("NUM_DAYS"));
            for (int i = 1; i <= numDays; i++)
            {
                Day newDay;
                String date = Integer.toString(depDate + (i-1));
                Meal breakfast;
                Meal lunch;
                Meal dinner;
                Incidental incidental;
                Lodging lodging;
                
                String city;
                String state;
                String country;
                
                Destination dest;
                Vector<Destination> destinations = new Vector<Destination>();
                
                double amount;
                String currency;
                String justification;
                
                // get breakfast
                if (formData.get("DAY"+String.valueOf(i)+"_BREAKFAST_CITY") == (null))
                {
                    city = "";
                }
                else 
                {
                    city = formData.get("DAY"+String.valueOf(i)+"_BREAKFAST_CITY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_BREAKFAST_STATE") == (null))
                {
                    state = "";
                }
                else
                {
                    state = formData.get("DAY"+String.valueOf(i)+"_BREAKFAST_STATE");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_BREAKFAST_COUNTRY") == (null))
                {
                    country = "";
                }
                else
                {
                    country = formData.get("DAY"+String.valueOf(i)+"_BREAKFAST_COUNTRY");
                }
                breakfast = new Meal(city, state, country);
                
                //add a destination
                destinations = newForm.getDestinations();
                boolean sameDestination = false;
                if(destinations!=null)
                {
                    for(int j=0;j<destinations.size();j++)
                    {
                        dest = destinations.get(j);
                        if( (dest.getCity().equalsIgnoreCase(city)) && (dest.getState().equalsIgnoreCase(state)) && (dest.getCountry().equalsIgnoreCase(country)))
                        {
                            sameDestination = true;
                            break;
                        }
                    
                    }
                    if(!sameDestination)
                    {
                        newForm.addDestination(new Destination(city, state, country));
                    }
                }
                
                // get lunch 
                if (formData.get("DAY"+String.valueOf(i)+"_LUNCH_CITY") == null)
                {
                    city = "";
                }
                else
                {
                    city = formData.get("DAY"+String.valueOf(i)+"_LUNCH_CITY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_LUNCH_STATE") == null)
                {
                    state = "";
                }
                else
                {
                    state = formData.get("DAY"+String.valueOf(i)+"_LUNCH_STATE");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_LUNCH_COUNTRY") == null)
                {
                    country = "";
                }
                else
                {
                    country = formData.get("DAY"+String.valueOf(i)+"_LUNCH_COUNTRY");
                }
                lunch = new Meal(city, state, country);
                
                //add a destination
                destinations = newForm.getDestinations();
                sameDestination = false;
                if(destinations!=null)
                {
                    for(int j=0;j<destinations.size();j++)
                    {
                        dest = destinations.get(j);
                        if( (dest.getCity().equalsIgnoreCase(city)) && (dest.getState().equalsIgnoreCase(state)) && (dest.getCountry().equalsIgnoreCase(country)))
                        {
                            sameDestination = true;
                            break;
                        }
                        
                    }
                     if(!sameDestination)
                    {
                        newForm.addDestination(new Destination(city, state, country));
                    }
                }
                // get dinner
                if (formData.get("DAY"+String.valueOf(i)+"_DINNER_CITY") == null)
                {
                    city = "";
                }
                else
                {
                    city = formData.get("DAY"+String.valueOf(i)+"_DINNER_CITY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_DINNER_STATE") == null)
                {
                    state = "";
                }
                else
                {
                    state = formData.get("DAY"+String.valueOf(i)+"_DINNER_STATE");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_DINNER_COUNTRY") == null)
                {
                    country = "";
                }
                else
                {
                    country = formData.get("DAY"+String.valueOf(i)+"_DINNER_COUNTRY");
                }
                dinner = new Meal(city, state, country);
                
                //add a destination
                destinations = newForm.getDestinations();
                sameDestination = false;
                if(destinations!=null)
                {
                    for(int j=0;j<destinations.size();j++)
                    {
                        dest = destinations.get(j);
                        if( (dest.getCity().equalsIgnoreCase(city)) && (dest.getState().equalsIgnoreCase(state)) && (dest.getCountry().equalsIgnoreCase(country)))
                        {
                            sameDestination = true;
                            break;
                        }
                        
                    }
                    if(!sameDestination)
                    {
                        newForm.addDestination(new Destination(city, state, country));
                    }
                }
                
                // get incidentals
                if (formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_CITY") == (null))
                {
                    city = "";
                }
                else
                {
                    city = formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_CITY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_STATE") == null)
                {
                    state = "";
                }
                else
                {
                    state = formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_STATE");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_COUNTRY") == null)
                {
                    country = "";
                }
                else
                {
                    country = formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_COUNTRY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_AMOUNT") == null)
                {
                    amount = 0;
                }
                else
                {
                    amount = Double.parseDouble(formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_AMOUNT"));
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_CURRENCY") == null)
                {
                    currency = "";
                }
                else
                {
                    currency = formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_CURRENCY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_JUSTIFICATION") == null)
                {
                    justification = "";
                }
                else
                {
                    justification = formData.get("DAY"+String.valueOf(i)+"_INCIDENTAL_JUSTIFICATION");
                }
                // perform conversion to USD
                if (!currency.equals("USD") && !currency.equals(""))
                {
                    // perform conversion to USD
                    try
                    {
                        amount = amount * currencyDB.getConversion(currency, String.valueOf(date));
                    }
                    catch(KeyNotFoundException e)
                    {
                        throw new CurrencyException("Currency type " + currency + " not found in the currency database");
                        
                    }
                    currency = "USD";
                }
                incidental = new Incidental(city, state, country, amount, currency, justification);
                
                //add a destination
                destinations = newForm.getDestinations();
                sameDestination = false;
                if(destinations!=null)
                {
                    for(int j=0;j<destinations.size();j++)
                    {
                        dest = destinations.get(j);
                        if( (dest.getCity().equalsIgnoreCase(city)) && (dest.getState().equalsIgnoreCase(state)) && (dest.getCountry().equalsIgnoreCase(country)))
                        {
                            sameDestination = true;
                            break;
                        }
                        
                    }
                    if(!sameDestination)
                    {
                        newForm.addDestination(new Destination(city, state, country));
                    }
                }
                
                // get lodging
                if (formData.get("DAY"+String.valueOf(i)+"_LODGING_CITY") == null)
                {
                    city = "";
                }
                else
                {
                    city = formData.get("DAY"+String.valueOf(i)+"_LODGING_CITY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_LODGING_STATE") == null)
                {
                    state = "";
                }
                else
                {
                    state = formData.get("DAY"+String.valueOf(i)+"_LODGING_STATE");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_LODGING_COUNTRY") == null)
                {
                    country = "";
                }
                else
                {
                    country = formData.get("DAY"+String.valueOf(i)+"_LODGING_COUNTRY");
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_LODGING_AMOUNT") == null)
                {
                    amount = 0;
                }
                else
                {
                    amount = Double.parseDouble(formData.get("DAY"+String.valueOf(i)+"_LODGING_AMOUNT"));
                }
                
                if (formData.get("DAY"+String.valueOf(i)+"_LODGING_CURRENCY") == null)
                {
                    currency = "";
                }
                else
                {
                    currency = formData.get("DAY"+String.valueOf(i)+"_LODGING_CURRENCY");
                }
                // perform conversion to USD
                if (!currency.equals("USD") && !currency.equals(""))
                {
                    // perform conversion to USD
                    try
                    {
                        amount = amount * currencyDB.getConversion(currency, String.valueOf(date));
                    }
                    catch(KeyNotFoundException e)
                    {
                        throw new CurrencyException("Currency type " + currency + " not found in the currency database");
                    }
                    currency = "USD";
                }
                lodging = new Lodging(city, state, country, amount, currency);
                
                //add a destination
                destinations = newForm.getDestinations();
                sameDestination = false;
                if(destinations!=null)
                {
                    for(int j=0;j<destinations.size();j++)
                    {
                        dest = destinations.get(j);
                        if( (dest.getCity().equalsIgnoreCase(city)) && (dest.getState().equalsIgnoreCase(state)) && (dest.getCountry().equalsIgnoreCase(country)))
                        {
                            sameDestination = true;
                            break;
                        }
                            
                    }
                    if(!sameDestination)
                    {
                        newForm.addDestination(new Destination(city, state, country));
                    }
                }
                
                newDay = new Day(date, breakfast, lunch, dinner, incidental, lodging);
                newForm.addDay(newDay);
            }
            
            // 3) fill in transportation and add to transportation vec
            if(formData.get("NUM_TRANSPORTATION") != null)
            {
	            int numTransports = Integer.parseInt(formData.get("NUM_TRANSPORTATION"));
	            for (int i = 1; i <= numTransports; i++)
	            {
	                String date;
	                String type;
	                boolean rental;
	                String carrier;
	                double miles;
	                double amount;
	                String currency;
	                
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_DATE") == null)
	                {
	                    date = "";
	                }
	                   else
	                {
	                    date = formData.get("TRANSPORTATION"+String.valueOf(i)+"_DATE");
	                }
	                   
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_TYPE") == null)
	                {
	                    type = "";
	                }
	                   else
	                   {
	                    type = formData.get("TRANSPORTATION"+String.valueOf(i)+"_TYPE");
	                }
	                   
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_RENTAL") == null)
	                {
	                    rental = false;
	                }
	                   else
	                   {
	                    rental = Boolean.parseBoolean(formData.get("TRANSPORTATION"+String.valueOf(i)+"_RENTAL"));
	                }
	                   
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_CARRIER") == null)
	                {
	                    carrier = "";
	                }
	                   else
	                   {
	                    carrier = formData.get("TRANSPORTATION"+String.valueOf(i)+"_CARRIER");
	                }
	                   
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_MILES_TRAVELED") == null)
	                {
	                    miles = 0;
	                }
	                   else
	                   {
	                    miles = Double.parseDouble(formData.get("TRANSPORTATION"+String.valueOf(i)+"_MILES_TRAVELED"));
	                }
	                       
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_AMOUNT") == null)
	                {
	                    amount = 0;
	                }
	                   else
	                   {
	                    amount = Double.parseDouble(formData.get("TRANSPORTATION"+String.valueOf(i)+"_AMOUNT"));
	                }
	                   
	                   if (formData.get("TRANSPORTATION"+String.valueOf(i)+"_CURRENCY") == null)
	                {
	                    currency = "";
	                }
	                   else
	                   {
	                    currency = formData.get("TRANSPORTATION"+String.valueOf(i)+"_CURRENCY");
	                }
	                // perform conversion to USD
	                if (!currency.equals("USD") && !currency.equals(""))
	                {
	                    // perform conversion to USD
	                    try
	                    {
	                        amount = amount * currencyDB.getConversion(currency, String.valueOf(date));
	                    }
	                    catch(KeyNotFoundException e)
	                    {
	                        throw new CurrencyException("Currency type " + currency + " not found in the currency database");
	                    }
	                    currency = "USD";
	                }
                	Transportation transport = new Transportation(i, date, amount, miles, rental, currency, type, carrier);
                	newForm.addTransportation(transport);
	            }
            }
            
            // 4) fill in otherExpenses and add to otherExpenses Vec
            if(formData.get("NUM_OTHER_EXPENSES") != null)
            {
	            int numOthers = Integer.parseInt(formData.get("NUM_OTHER_EXPENSES"));
	            for (int i = 1; i <= numOthers; i++)
	            {
	                String date;
	                String justification;
	                double amount;
	                String currency;
	                
	                   if (formData.get("OTHER"+String.valueOf(i)+"_DATE") == null)
	                {
	                    date = "";
	                }
	                   else
	                   {
	                    date = formData.get("OTHER"+String.valueOf(i)+"_DATE");
	                }
	                        
	                   if (formData.get("OTHER"+String.valueOf(i)+"_JUSTIFICATION") == null)
	                {
	                    justification = "";
	                }
	                   else
	                   {
	                    justification = formData.get("OTHER"+String.valueOf(i)+"_JUSTIFICATION");
	                }
	                   
	                   if (formData.get("OTHER"+String.valueOf(i)+"_AMOUNT") == null)
	                {
	                    amount = 0;
	                }
	                   else
	                   {
	                    amount = Double.parseDouble(formData.get("OTHER"+String.valueOf(i)+"_AMOUNT"));
	                }
	                   
	                   if (formData.get("OTHER"+String.valueOf(i)+"_CURRENCY") == null)
	                {
	                    currency = "";
	                }
	                   else
	                   {
	                    currency = formData.get("OTHER"+String.valueOf(i)+"_CURRENCY");
	                }
	                // perform conversion to USD
	                if (!currency.equals("USD") && !currency.equals(""))
	                {
	                    // perform conversion to USD
	                    try
	                    {
	                        amount = amount * currencyDB.getConversion(currency, String.valueOf(date));
	                    }
	                    catch(KeyNotFoundException e)
	                    {
	                        throw new CurrencyException("Currency type " + currency + " not found in the currency database");
	                    }
	                    currency = "USD";
	                }
	                                                             
	                OtherExpenses otherExps = new OtherExpenses(date, amount, currency, justification);
	                newForm.addOtherExpenses(otherExps);
	            }
            }
            
            // 5) fill in grants and add to grants Vec
            int numGrants = Integer.parseInt(formData.get("NUM_GRANTS"));
            for (int i = 1; i <= numGrants; i++)
            {
                String accountNum;
                int percent;
                
                   if (formData.get("GRANT"+String.valueOf(i)+"_ACCOUNT") == null)
                {
                    accountNum = "";
                }
                   else
                   {
                    accountNum = (formData.get("GRANT"+String.valueOf(i)+"_ACCOUNT"));
                }
                   
                   if (formData.get("GRANT"+String.valueOf(i)+"_PERCENT") == null)
                {
                       percent = 0;
                }
                   else
                   {
                    percent = Integer.parseInt(formData.get("GRANT"+String.valueOf(i)+"_PERCENT"));
                }
                   
                   Grant grant = new Grant(i, accountNum, percent);
                   newForm.addGrant(grant);
            }
    
        }
        catch(Exception e)
        {
            e.printStackTrace();
             throw new TrapException("Exception in Formfactory.createForm()");
         }
        
        return newForm;
    }
}